import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { SysUser } from './entities/user.entity';
import { UserForm, UserInfoVO } from './dto/user.response';
import { PageResult } from '../../common/result/PageResult';
import {
  UserModelAdd,
  UserModelUpdate,
  UserPageQuery,
} from './dto/user.request';
import { SystemConstant } from '../../common/constant/SystemConstant';
import { generator } from '../../common/utils/generator';
import { Result } from '../../common/result/Result';
import { ResultCode } from '../../common/result/ResultCode';
import { SysUserRole } from './entities/user.role.entity';
import { JwtPayload } from '../01_auth/jwt.payload';
import * as multer from 'multer';
import * as fs from 'fs';

@Injectable()
export class UserService {
  // 依赖配置注入
  constructor(
    @InjectRepository(SysUser)
    private usersRepository: Repository<SysUser>, // mysql数据库连接工具
    @InjectRepository(SysUserRole)
    private usersRoleRepository: Repository<SysUserRole>, // mysql数据库连接工具
  ) {}

  async getCurrentUserInfo(payload: JwtPayload): Promise<UserInfoVO> {
    // 1. 根据
    const dbUser = await this.usersRepository.findOne({
      where: { id: payload.userId },
    });
    const userInfoVO = new UserInfoVO();
    userInfoVO.userId = dbUser.id;
    userInfoVO.nickname = dbUser.nickname;
    userInfoVO.avatar = dbUser.avatar;
    userInfoVO.username = dbUser.username;
    userInfoVO.perms = await this.getPerms(payload.userId);
    userInfoVO.roles = await this.getRoles(payload.userId);
    return userInfoVO;
  }

  async getRoles(userId: number): Promise<string[]> {
    const roles: [] = await this.usersRepository.query(
      `SELECT DISTINCT code FROM sys_role 
WHERE id IN (SELECT role_id FROM sys_user_role WHERE user_id = @0)`,
      [userId],
    );
    const res = [];
    roles.forEach((role) => {
      res.push(role['code']);
    });
    return res; // 修正了箭头函数的语法错误
  }
  async getRoleIds(userId: number): Promise<string[]> {
    const roles: [] = await this.usersRepository.query(
      `SELECT DISTINCT id FROM sys_role 
WHERE id IN (SELECT role_id FROM sys_user_role WHERE user_id = @0)`,
      [userId],
    );
    const res = [];
    roles.forEach((role) => {
      res.push(role['id']);
    });
    return res; // 修正了箭头函数的语法错误
  }

  async getPage(query: UserPageQuery): Promise<PageResult<SysUser>> {
    const queryBuilder = this.usersRepository
      .createQueryBuilder('su')
      .skip((query.pageNum - 1) * query.pageSize)
      .take(query.pageSize);
    if (query.deptId) {
      queryBuilder.andWhere('su.deptId = :deptId', { deptId: query.deptId });
    }
    if (query.startTime && query.endTime) {
      queryBuilder.andWhere('su.createTime BETWEEN :startTime AND :endTime', {
        startTime: query.startTime,
        endTime: query.endTime,
      });
    }
    if (query.keywords) {
      queryBuilder.andWhere(
        '(su.mobile LIKE :keywords OR su.nickname LIKE :keywords OR su.username LIKE :keywords)',
        { keywords: `%${query.keywords}%` },
      );
    }
    const result = await queryBuilder.getManyAndCount();
    return PageResult.success(result[0], result[1]);
  }

  private async getPerms(userId: number): Promise<string[]> {
    const perms: any[] = await this.usersRepository.query(
      `SELECT DISTINCT m.perm 
FROM sys_menu m 
INNER JOIN ( 
   SELECT DISTINCT menu_id 
   FROM sys_role_menu 
   INNER JOIN sys_user_role ON sys_role_menu.role_id = sys_user_role.role_id 
   WHERE sys_user_role.user_id = @0
) rm ON m.id = rm.menu_id 
WHERE perm IS NOT NULL;`,
      [userId],
    );
    const res = [];
    perms.forEach((perm) => {
      res.push(perm['perm']);
    });
    return res; // 修正了箭头函数的语法错误
  }

  async saveUser(
    form: UserModelAdd,
    currentUser: JwtPayload,
  ): Promise<Result<string>> {
    // 1. 校验用户是否存在
    const flag = await this.usersRepository.exists({
      where: { username: form.username },
    });
    if (flag) {
      return Result.failed(ResultCode.USER_HAS_CREATE);
    }
    const user = new SysUser({
      createUser: currentUser.username,
      createBy: currentUser.userId,
      updateUser: currentUser.username,
      updateBy: currentUser.userId,
    });
    // 2. 生成默认密码
    user.password = generator.PasswordEncode(SystemConstant.DEFAULT_PASSWORD);
    // 3. 插入用户表信息
    user.username = form.username;
    user.nickname = form.nickname;
    user.mobile = form.mobile;
    user.gender = form.gender;
    user.avatar = form.avatar;
    user.email = form.email;
    user.deptId = form.deptId;
    user.status = form.status;
    await this.usersRepository.save(user);
    await this.saveUserRoles(user.id, form.roleIds);
    return Result.success();
  }

  async deleteUser(ids: string): Promise<Result<string>> {
    // 删除用户
    for (const id of ids.split(',')) {
      await this.usersRepository.softDelete({ id: Number(id) });
      await this.usersRoleRepository.delete({ userId: Number(id) });
    }
    return Result.success();
  }

  async updateUser(form: UserModelUpdate): Promise<Result<string>> {
    const user = new SysUser({
      updateUser: form.nickname,
      updateBy: form.userId,
    });
    user.username = form.username;
    user.nickname = form.nickname;
    user.mobile = form.mobile;
    user.gender = form.gender;
    user.avatar = form.avatar;
    user.email = form.email;
    user.deptId = form.deptId;
    user.status = form.status;
    await this.usersRepository.update({ id: form.id }, user);
    await this.saveUserRoles(form.id, form.roleIds);
    return Result.success();
  }

  async saveUserRoles(userId: number, roleIds: number[]) {
    // 先删除该用户的角色
    await this.usersRoleRepository.delete({ userId: userId });
    // 插入新的用户角色
    for (const roleId of roleIds) {
      await this.usersRoleRepository.insert(new SysUserRole(userId, roleId));
    }
  }

  async getUserForm(userId: number): Promise<Result<UserForm>> {
    const user = await this.usersRepository.findOne({ where: { id: userId } });
    const userForm = new UserForm({
      avatar: user.avatar,
      deptId: user.deptId,
      email: user.email,
      gender: user.gender,
      id: user.id,
      mobile: user.mobile,
      nickname: user.nickname,
      status: user.status,
      username: user.username,
      roleIds: await this.getRoleIds(userId),
    });
    return Result.success(userForm);
  }

  async updatePassword(id: number, password: string): Promise<Result<any>> {
    const result = await this.usersRepository.update(
      { id: id },
      {
        password: generator.PasswordEncode(password),
      },
    );
    return Result.success(result);
  }

  async updateStatus(id: number, status: number): Promise<Result<any>> {
    const result = await this.usersRepository.update(
      { id: id },
      {
        status: status,
      },
    );
    return Result.success(result);
  }
}
